;function charString(char, count) {
    var str = "";
    while (count--) {
        str += char
    }
    return str
}
;Date.prototype.format = function(format) {
    var map = {
        "y": this.getFullYear() + "",
        "M": this.getMonth() + 1 + "",
        "d": this.getDate() + "",
        "H": this.getHours(),
        "m": this.getMinutes() + "",
        "s": this.getSeconds() + "",
        "q": Math.floor((this.getMonth() + 3) / 3) + "",
        "f": this.getMilliseconds() + ""
    };
    if (map["H"] > 12) {
        map["h"] = map["H"] - 12 + ""
    } else {
        map["h"] = map["H"] + ""
    }
    map["H"] += "";
    var reg = "yMdHhmsqf";
    var all = ""
      , str = "";
    for (var i = 0, n = 0; i < reg.length; i++) {
        n = format.indexOf(reg[i]);
        if (n < 0) {
            continue
        }
        ;all = "";
        for (; n < format.length; n++) {
            if (format[n] != reg[i]) {
                break
            }
            all += reg[i]
        }
        if (all.length > 0) {
            if (all.length == map[reg[i]].length) {
                str = map[reg[i]]
            } else if (all.length > map[reg[i]].length) {
                if (reg[i] == "f") {
                    str = map[reg[i]] + charString("0", all.length - map[reg[i]].length)
                } else {
                    str = charString("0", all.length - map[reg[i]].length) + map[reg[i]]
                }
            } else {
                switch (reg[i]) {
                case "y":
                    str = map[reg[i]].substr(map[reg[i]].length - all.length);
                    break;
                case "f":
                    str = map[reg[i]].substr(0, all.length);
                    break;
                default:
                    str = map[reg[i]];
                    break
                }
            }
            format = format.replace(all, str)
        }
    }
    return format
}
;
function isNullOrEmpty(str) {
    if (str == null) {
        return true
    }
    if (str == "") {
        return true
    }
    let type = typeof (str);
    if (type != "string" && type != "number") {
        console.error("isNullOrEmpty error type", str)
    }
    return false
}
;let kSortSign = [1, -1];
function KVDataSort(a, b) {
    if (a.rawValues == null && b.rawValues == null) {
        return 0
    } else if (a.rawValues == null) {
        return 1
    } else if (b.rawValues == null) {
        return -1
    }
    let aVals = a.rawValues;
    let bVals = b.rawValues;
    for (let index = 0; index < aVals.length; index++) {
        let aVal = aVals[index];
        let bVal = bVals[index];
        let sign = kSortSign[index] || 1;
        if (aVal == bVal) {
            continue
        } else {
            return (bVal - aVal) * sign
        }
    }
    ;return 0
}
;class _WeChatSDK {
    constructor(sortSign) {
        if (sortSign == null) {
            sortSign = [1, -1];
            console.error("WeChatSDK sortSign null, use Default [1, -1]")
        }
        kSortSign = sortSign;
        this._weekStartTime = 0
    }
    ;getUserInfo(sussCallback, failCallback) {
        wx.getUserInfo({
            openIdList: ['selfOpenId'],
            success: (res)=>{
                let userData = res.data[0];
                sussCallback(userData)
            }
            ,
            fail: (res)=>{
                console.error("getUserInfo fail", JSON.stringify(res));
                if (failCallback != null) {
                    failCallback()
                }
            }
        })
    }
    ;getUserCloudStorage(key, sussCallback, failCallback) {
        wx.getUserCloudStorage({
            keyList: [key],
            success: (data)=>{
                sussCallback(data)
            }
            ,
            fail: (res)=>{
                console.error("getUserCloudStorage fail", key, JSON.stringify(res));
                if (failCallback != null) {
                    failCallback()
                }
            }
        })
    }
    ;setUserCloudStorage(key, datas, sussCallback, failCallback) {
        let now = new Date();
        datas.push(Math.round(now.getTime() * 0.001));
        let list = [{
            key: key,
            value: JSON.stringify(datas)
        }];
        wx.setUserCloudStorage({
            keyList: [key],
            KVDataList: list,
            success: function(data) {
                if (sussCallback != null) {
                    sussCallback()
                }
            },
            fail: function(res) {
                console.error("setUserCloudStorage fail", key, JSON.stringify(res));
                if (failCallback != null) {
                    failCallback()
                }
            }
        })
    }
    ;updateUserCloudStorage(key, datas, sussCallback, failCallback) {
        this._weekStartTime = 0;
        this.getUserCloudStorage(key, (data)=>{
            if (data.KVDataList.length > 0) {
                let records = JSON.parse(data.KVDataList[0].value);
                if (!this.isBetter(datas, records)) {
                    return
                }
            }
            this.setUserCloudStorage(key, datas, sussCallback, failCallback)
        }
        , function() {
            console.error("updateUserCloudStorage get fail:", key);
            if (failCallback != null) {
                failCallback()
            }
        })
    }
    ;isBetter(datas, records, weekly) {
        let weekStartTime = this.getWeekStartTime();
        if (weekly && records[records.length - 1] < weekStartTime) {
            return true
        }
        let suss = true;
        for (let index = 0; index < datas.length; index++) {
            let aVal = records[index] || 0;
            let bVal = datas[index];
            let sign = kSortSign[index] || 1;
            if (sign > 0) {
                if (aVal > bVal) {
                    suss = false;
                    break
                }
            } else {
                if (aVal < bVal) {
                    suss = false;
                    break
                }
            }
        }
        console.info("update rank", suss, JSON.stringify(datas), "record", JSON.stringify(records));
        return suss
    }
    ;getWeekStartTime() {
        if (this._weekStartTime == 0) {
            let now = new Date();
            let week = now.getDay();
            let minusDay = week != 0 ? week - 1 : 6;
            let weekStart = new Date(now.getFullYear(),now.getMonth(),now.getDate() - minusDay);
            this._weekStartTime = Math.round(weekStart.getTime() * 0.001)
        }
        return this._weekStartTime
    }
    ;parseDatas(datas, weekly) {
        let weekStartTime = this.getWeekStartTime();
        let array = [];
        for (let index = 0; index < datas.length; index++) {
            let data = datas[index];
            if (data.KVDataList.length == 0) {
                continue
            }
            if (data.nickName == null) {
                data.nickName = data.nickname;
                delete data.nickname
            }
            let vals = JSON.parse(data.KVDataList[0].value);
            if (weekly && vals[vals.length - 1] < weekStartTime) {
                continue
            }
            data.rawValues = vals;
            delete data.KVDataList;
            array.push(data)
        }
        return array
    }
    ;getFriendCloudStorage(key, sussCallback, failCallback) {
        this._weekStartTime = 0;
        wx.getFriendCloudStorage({
            keyList: [key],
            success: (res)=>{
                let data = this.parseDatas(res.data);
                data.sort(KVDataSort);
                sussCallback(data)
            }
            ,
            fail: function(res) {
                cc.error("getFriendCloudStorage get fail:", key);
                if (failCallback != null) {
                    failCallback()
                }
            }
        })
    }
    ;getGroupCloudStorage(key, shareTicket, sussCallback, failCallback) {
        wx.getGroupCloudStorage({
            shareTicket: shareTicket,
            keyList: [key],
            success: (res)=>{
                let data = this.parseDatas(res.data);
                data.sort(KVDataSort);
                console.info("group sort:", JSON.stringify(data));
                sussCallback(data)
            }
            ,
            fail: function(res) {
                console.error("getGroupCloudStorage get fail:", key);
                if (failCallback != null) {
                    failCallback()
                }
            }
        })
    }
}
const WeChatSDK = new _WeChatSDK([1, -1]);
const kPageSize = 5;
const kRankItemWidth = 600;
const kRankItemHeight = 117;
const kRankItemGap = 5;
const kRankPageHeight = (kRankItemHeight + kRankItemGap) * kPageSize;
const kRankAvatarWidth = 60;
const kRankAvatarHeight = 60;
const kFontSize = 30;
const kRankHeight = kRankPageHeight + 70;
const kBgHeadWidth = 40;
const kBgHeadHeight = 40;
const kIconRankWidth = 53;
const kIconRankHeight = 69;
const kTopAvatarWidth = 60;
const kTopAvatarHeight = 60;
const kGrades = ["D", "C", "B", "A", "S", "S+"];
const kAccuracy2Grades = [60, 70, 80, 90, 95, 100];
class RankListRenderer {
    constructor() {
        this.clearFlag = false;
        this.offsetY = 0;
        this.maxOffsetY = 0;
        this.gameDatas = [];
        this.curKey = null;
        this.curPageIndex = 0;
        this.rankCanvasList = [];
        this.selfRank = 0;
        this.selfUserInfo = null;
        this.init()
    }
    ;init() {
        this.sharedCanvas = wx.getSharedCanvas();
        this.sharedCtx = this.sharedCanvas.getContext('2d');
        WeChatSDK.getUserInfo(data=>{
            this.selfUserInfo = data
        }
        );
        setTimeout(()=>{
            this.preload()
        }
        , 1)
    }
    ;preload() {
        this.iconRanks = [];
        this.bgRanks = [];
        for (let index = 0; index < 3; index++) {
            this.iconRanks.push(null);
            const iconRank = wx.createImage();
            iconRank.src = `subcontext/res/rank_${index + 1}.png`;
            iconRank.onload = ()=>{
                this.iconRanks[index] = iconRank
            }
        }
        for (let index = 0; index < 4; index++) {
            this.bgRanks.push(null);
            const bgRank = wx.createImage();
            bgRank.src = `subcontext/res/bg_${index + 1}.png`;
            bgRank.onload = ()=>{
                this.bgRanks[index] = bgRank
            }
        }
        this.surpassSrc = [];
        for (let index = 0; index < 2; index++) {
            this.surpassSrc.push(null);
            const surSrc = wx.createImage();
            surSrc.src = `subcontext/res/surpass_${index + 1}.png`;
            surSrc.onload = ()=>{
                this.surpassSrc[index] = surSrc
            }
        }
        this.avatars = {};
        this.avatarWaitCnt = 0;
        this.avatarNeedRefresh = false
    }
    ;drawAvatar(avatarUrl, callback) {
        if (isNullOrEmpty(avatarUrl)) {
            console.error("drawAvatar avatarUrl null");
            return
        }
        let avatar = this.avatars[avatarUrl];
        if (avatar != null) {
            callback(avatar);
            return
        }
        this.avatarWaitCnt = this.avatarWaitCnt + 1;
        avatar = wx.createImage();
        avatar.src = avatarUrl;
        avatar.onload = ()=>{
            this.avatarWaitCnt = this.avatarWaitCnt - 1;
            if (this.avatarWaitCnt == 0) {
                this.avatarNeedRefresh = true
            }
            this.avatars[avatarUrl] = avatar;
            callback(avatar)
        }
    }
    ;listen() {
        wx.onMessage(msg=>{
            switch (msg.cmd) {
            case "showRank":
                this.clearFlag = true;
                this.showRank(msg);
                break;
            case "pageRank":
                if (this.gameDatas == null) {
                    return
                }
                this.clearFlag = false;
                const page = msg.value;
                this.curPageIndex += page;
                if (this.curPageIndex < 0) {
                    this.curPageIndex = 0;
                    return
                } else if (this.curPageIndex > this.maxPage) {
                    this.curPageIndex = this.maxPage;
                    return
                }
                this.offsetY = kRankPageHeight * this.curPageIndex;
                this.refreshRank();
                break;
            case "scrollRank":
                if (this.gameDatas == null) {
                    return
                }
                this.clearFlag = false;
                const deltaY = msg.value;
                const newOffsetY = this.offsetY + deltaY;
                if (newOffsetY < 0) {
                    return
                }
                if (newOffsetY + kRankPageHeight > this.maxOffsetY) {
                    return
                }
                this.curPageIndex = Math.floor(this.offsetY / kRankPageHeight);
                this.offsetY = newOffsetY;
                this.refreshRank();
                break;
            case "updateRecord":
                let key = this.getKey(msg);
                WeChatSDK.updateUserCloudStorage(key, msg.datas);
                break;
            case "surpass":
                this.showSurpassFriend(msg);
                break;
            default:
                console.error("wx.onMessage error cmd", JSON.stringify(msg));
                break;
            }
        }
        )
    }
    ;getKey(msg) {
        return "rank_" + msg.id
    }
    ;showRank(msg) {
        const sharedWidth = this.sharedCanvas.width;
        const sharedHeight = this.sharedCanvas.height;
        this.sharedCtx.clearRect(0, 0, sharedWidth, sharedHeight);
        let key = this.getKey(msg);
        this.curKey = key;
        this.gameDatas = null;
        WeChatSDK.getFriendCloudStorage(key, (datas)=>{
            if (this.curKey != key) {
                return
            }
            this.gameDatas = datas;
            const dataLen = this.gameDatas.length;
            this.offsetY = 0;
            this.maxOffsetY = dataLen * kRankItemHeight;
            this.curPageIndex = 0;
            this.maxPage = Math.ceil(dataLen / kPageSize) - 1;
            this.refreshRank()
        }
        )
    }
    ;showSurpassFriend(msg) {
        const sharedWidth = this.sharedCanvas.width;
        const sharedHeight = this.sharedCanvas.height;
        this.sharedCtx.clearRect(0, 0, sharedWidth, sharedHeight);
        let key = this.getKey(msg);
        this.curKey = key;
        this.gameDatas = null;
        this.selfRank = 0;
        WeChatSDK.getFriendCloudStorage(key, (datas)=>{
            if (this.curKey != key) {
                return
            }
            this.gameDatas = datas;
            if (!this.gameDatas || !this.gameDatas.length)
                return;
            this.refreshSurpassRank(msg.openid)
        }
        )
    }
    ;getSurpassData(openid) {
        let dataList = [];
        if (this.gameDatas.length == 1) {
            if (this.gameDatas[0].openid == openid) {
                this.selfRank = 1;
                return this.gameDatas
            }
        }
        if (this.gameDatas.length == 2 || this.gameDatas.length == 3) {
            for (let i = 0; i < this.gameDatas.length; i++) {
                if (this.gameDatas[i].openid == openid) {
                    this.selfRank = i + 1;
                    break
                }
            }
            return this.gameDatas
        }
        if (this.gameDatas.length > 3) {
            for (let i = 0; i < this.gameDatas.length; i++) {
                if (this.gameDatas[i].openid == openid) {
                    this.selfRank = i + 1;
                    break
                }
            }
        }
        if (this.selfRank == 1) {
            dataList = [this.gameDatas[0], this.gameDatas[1], this.gameDatas[2]]
        } else {
            dataList = [this.gameDatas[this.selfRank - 2], this.gameDatas[this.selfRank - 1], this.gameDatas[this.selfRank]]
        }
        return dataList
    }
    ;refreshSurpassRank(openid) {
        const sharedWidth = this.sharedCanvas.width;
        const sharedHeight = this.sharedCanvas.height;
        this.sharedCtx.clearRect(0, 0, sharedWidth, sharedHeight);
        if (this.clearFlag) {
            this.clearFlag = false
        }
        let list = this.getSurpassData(openid);
        console.log("========超越好友显示列表========", list);
        for (let i = 0; i < list.length; i++) {
            this.drawAvatar(list[i].avatarUrl, (avatar)=>{
                this.sharedCtx.drawImage(avatar, 50 + i * 160, 40, 90, 90);
                if (this.avatarNeedRefresh) {
                    this.avatarNeedRefresh = false;
                    this.refreshSurpassRank(openid)
                }
            }
            );
            let nick = list[i].nickName || list[i].nickname || "热血猎手";
            let name = nick.length > 6 ? nick.slice(0, 6) : nick;
            this.sharedCtx.fillStyle = "#FFFFFF";
            this.sharedCtx.textAlign = "center";
            this.sharedCtx.baseLine = "middle";
            this.sharedCtx.font = `bold ${20}px Arial`;
            this.sharedCtx.fillText(name, 100 + i * 160, 152);
            this.sharedCtx.drawImage(this.surpassSrc[0], 40 + i * 160, 18, 32, 41);
            this.sharedCtx.fillStyle = "#FFFFFF";
            this.sharedCtx.textAlign = "center";
            this.sharedCtx.baseLine = "middle";
            this.sharedCtx.font = `bold ${20}px Arial`;
            if (this.selfRank == 1) {
                this.sharedCtx.fillText(this.selfRank + i, 57 + i * 160, 43)
            } else {
                this.sharedCtx.fillText(this.selfRank - 1 + i, 57 + i * 160, 43)
            }
        }
        if (this.selfRank > 1) {
            this.sharedCtx.drawImage(this.surpassSrc[1], 65, 115, 68, 19)
        }
    }
    ;refreshRank() {
        const sharedWidth = this.sharedCanvas.width;
        const sharedHeight = this.sharedCanvas.height;
        this.sharedCtx.clearRect(0, 0, sharedWidth, sharedHeight);
        if (this.clearFlag) {
            this.clearFlag = false;
            this.rankCanvasList = []
        }
        const pageY = this.offsetY % kRankPageHeight;
        const pageIndex = this.curPageIndex;
        const isOverOnePage = pageY + sharedHeight > kRankPageHeight;
        let rankCanvas = this.getCanvasByPageIndex(pageIndex);
        this.sharedCtx.drawImage(rankCanvas, 0, pageY, sharedWidth, sharedHeight, 0, 0, sharedWidth, sharedHeight);
        this.drawPageNum()
    }
    ;drawPageNum() {
        let curIndex = this.curPageIndex + 1 || 1;
        let maxPage = this.maxPage + 1 || 1;
        this.sharedCtx.fillStyle = "#FFFFFF";
        this.sharedCtx.textAlign = "center";
        this.sharedCtx.baseLine = "middle";
        this.sharedCtx.font = `bold ${kFontSize}px Arial`;
        this.sharedCtx.fillText(`${curIndex}${"/"}${maxPage}`, kRankItemWidth / 2, kRankHeight - kFontSize / 2)
    }
    ;getCanvasByPageIndex(pageIndex) {
        let canvas = this.rankCanvasList[pageIndex];
        if (!canvas) {
            canvas = wx.createCanvas();
            canvas.width = this.sharedCanvas.width;
            canvas.height = kRankHeight;
            this.rankCanvasList[pageIndex] = canvas;
            const ctx = canvas.getContext('2d');
            this.drawPagedRanks(ctx, pageIndex)
        }
        return canvas
    }
    ;drawPagedRanks(ctx, pageIndex) {
        const pageOffset = pageIndex * kPageSize;
        for (let i = 0; i < kPageSize; i++) {
            const data = this.gameDatas[pageOffset + i];
            if (data == null || data.rawValues == null) {
                continue
            }
            let rank = pageOffset + i + 1;
            let style = (rank - 1) % kPageSize % 2;
            this.drawRankItemEx(ctx, rank, data, (kRankItemHeight + kRankItemGap) * i, style)
        }
    }
    ;drawRankItemEx(ctx, rank, data, itemY, style) {
        const textOffsetY = kRankItemHeight / 2 + 5;
        if (rank != null) {
            if (rank <= 3) {
                let icon = this.bgRanks[rank - 1];
                if (icon != null) {
                    ctx.drawImage(icon, 0, itemY, kRankItemWidth, kRankItemHeight)
                }
            } else {
                let icon = this.bgRanks[3];
                if (icon != null) {
                    ctx.drawImage(icon, 0, itemY, kRankItemWidth, kRankItemHeight)
                }
            }
            if (rank <= this.iconRanks.length) {
                let icon = this.iconRanks[rank - 1];
                if (icon != null) {
                    ctx.drawImage(icon, 30, itemY + (kRankItemHeight - kIconRankHeight) / 2, kIconRankWidth, kIconRankHeight)
                }
            } else {
                ctx.fillStyle = "#FFFFFF";
                ctx.textAlign = "center";
                ctx.baseLine = "middle";
                ctx.font = `bold ${kFontSize}px Arial`;
                ctx.fillText(`${rank}`, 60, itemY + textOffsetY)
            }
        } else {
            ctx.fillStyle = "#FFFFFF";
            ctx.textAlign = "center";
            ctx.baseLine = "middle";
            ctx.font = `bold ${kFontSize}px Arial`;
            ctx.fillText(`?`, 60, itemY + textOffsetY)
        }
        this.drawAvatar(data.avatarUrl, (avatar)=>{
            ctx.drawImage(avatar, 100, itemY + (kRankItemHeight - kRankAvatarHeight) / 2, kRankAvatarWidth, kRankAvatarHeight);
            if (this.avatarNeedRefresh) {
                this.avatarNeedRefresh = false;
                this.refreshRank()
            }
        }
        );
        let nick = data.nickName || data.nickname || "unknown";
        let name = nick.length > 6 ? nick.slice(0, 6) : nick;
        ctx.fillStyle = "#FFFFFF";
        ctx.textAlign = "center";
        ctx.baseLine = "middle";
        ctx.font = `bold ${kFontSize}px Arial`;
        ctx.fillText(name, 260, itemY + textOffsetY);
        let scoreStr = data.rawValues[0].toString();
        ctx.fillStyle = "#FFFFFF";
        ctx.textAlign = "center";
        ctx.baseLine = "middle";
        ctx.font = `bold ${kFontSize}px Arial`;
        ctx.fillText(`${scoreStr}关`, 520, itemY + textOffsetY)
    }
}
const rankList = new RankListRenderer();
rankList.listen();
;